package impl

import (
	"context"

	"dario.cat/mergo"
	"gitee.com/shiwjlinux/vblog01/apps/blog"
	"gitee.com/shiwjlinux/vblog01/common"
	"gitee.com/shiwjlinux/vblog01/exception"
)

// QueryBlog函数用于查询博客
func (i *BlogServiceImpl) QueryBlog(ctx context.Context,
	in *blog.QueryBlogRequest,
) (*blog.BlogSet, error) {
	// 创建一个新的BlogSet
	set := blog.NewBlogSet()

	// 使用传入的context和数据库表名创建一个查询
	query := i.db.WithContext(ctx).Table(blog.AppName + "s")

	// 如果传入的关键词不为空，则添加关键词查询条件
	if in.Keywords != "" {
		query = query.Where("context LIKE ?", "%"+in.Keywords+"%")
	}

	// 如果传入的标题不为空，则添加标题查询条件
	if in.Title != "" {
		query = query.Where("title LIKE ?", "%"+in.Title+"%")
	}

	// 如果传入的ID不为空，则添加ID查询条件
	if in.Id != "" {
		query = query.Where("id = ?", in.Id)
	}

	// 如果传入的状态不为空，则添加状态查询条件
	if in.Status != nil {
		query = query.Where("status = ?", in.Status)
	}
	// 查询总条数
	if err := query.Count(&set.Total).Error; err != nil {
		return nil, err
	}

	// 查询数据，并按照创建时间降序排列
	if err := query.
		Offset(in.Offset()).
		Limit(in.PageSize).
		Find(&set.Items).
		Order("created_at DESC").
		Error; err != nil {
		return nil, err
	}

	// 返回查询结果
	return set, nil
}

func (i *BlogServiceImpl) DescribeBlog(ctx context.Context,
	in *blog.DescribeBlogRequest,
) (*blog.Blog, error) {
	ins := blog.NewBlog()
	if err := i.db.
		WithContext(ctx).
		Where("ID = ?", in.Id).
		First(ins).
		Error; err != nil {
		return nil, err
	}
	return ins, nil
}

// CreateBlog 方法用于创建博客
func (i *BlogServiceImpl) CreateBlog(ctx context.Context,
	in *blog.CreateBlogRequest,
) (*blog.Blog, error) {
	// 验证请求参数
	if err := in.Validate(); err != nil {
		// 如果验证失败，返回错误信息
		return nil, exception.ErrValidateFailed("%s %s",
			err.Error(), "CreateBlog")
	}

	// 创建一个新的博客实例
	ins := blog.NewBlog()
	ins.CreateBlogRequest = in

	// 将博客实例保存到数据库中
	if err := i.db.WithContext(ctx).Create(ins).Error; err != nil {
		// 如果保存失败，返回错误信息
		return nil, err
	}
	// 返回保存后的博客实例

	return ins, nil
}

// UpdateBlog函数用于更新博客
func (i *BlogServiceImpl) UpdateBlog(ctx context.Context,
	in *blog.UpdateBlogRequest,
) (*blog.Blog, error) {
	// 创建一个描述博客的请求
	desBlog := blog.NewDescribeBlogRequest(in.Id)
	// 调用DescribeBlog函数获取博客信息
	ins, err := i.DescribeBlog(ctx, desBlog)
	if err != nil {
		return nil, err
	}

	// 根据更新模式进行不同的更新操作
	switch in.UpdateMode {
	case common.UPDATE_MODE_PATCH:
		// 如果作者不为空，则更新作者
		if in.Author != "" {
			ins.Author = in.Author
		}
		// 如果内容不为空，则更新内容
		if in.Content != "" {
			ins.Content = in.Content
		}

		// 合并CreateBlogRequest
		err := mergo.MergeWithOverwrite(ins.CreateBlogRequest, in.CreateBlogRequest)
		if err != nil {
			return nil, err
		}
	case common.UPDATE_MODE_PUT:
		// 如果更新模式为PUT，则直接更新CreateBlogRequest
		ins.CreateBlogRequest = in.CreateBlogRequest

	}

	// 验证博客信息
	if err := ins.Validate(); err != nil {
		return nil, exception.ErrValidateFailed(err.Error())
	}

	// Gorm自动更新Updated_At字段

	// 更新数据库中的博客信息
	if err := i.db.
		WithContext(ctx).
		Table(ins.TableName()).
		Save(ins).
		Error; err != nil {
		return nil, err
	}

	return ins, nil
}

// 更新博客状态
func (i *BlogServiceImpl) UpdateBlogStatus(ctx context.Context,
	in *blog.UpdateBlogStatusRequest,
) (*blog.Blog, error) {
	// 根据博客ID查询博客信息
	ins, err := i.DescribeBlog(ctx, blog.NewDescribeBlogRequest(in.Id))
	if err != nil {
		return nil, err
	}

	// 设置博客状态
	ins.ChangedBlogStatusRequest = in.ChangedBlogStatusRequest
	in.SetStatus(*in.Status)

	// 更新数据库中的博客状态
	if err := i.db.
		WithContext(ctx).
		Table(ins.TableName()).
		Where("id = ?", in.Id).
		Updates(ins.ChangedBlogStatusRequest).
		Error; err != nil {
		return nil, err
	}

	return ins, nil
}

// DeleteBlog函数用于删除博客
func (i *BlogServiceImpl) DeleteBlog(ctx context.Context,
	in *blog.DeleteBlogRequest,
) (*blog.Blog, error) {
	// 根据博客ID查询博客信息
	ins, err := i.DescribeBlog(ctx, blog.NewDescribeBlogRequest(in.Id))
	if err != nil {
		return nil, err
	}

	// 检查权限？
	// 删除博客信息
	if err := i.db.
		WithContext(ctx).
		Where("id = ?", in.Id).
		Delete(&blog.Blog{}).
		Table(ins.TableName()).
		Error; err != nil {
		return nil, err
	}

	return ins, nil
}
